#ifndef __MQ_ROUTER_HPP__
#define __MQ_ROUTER_HPP__

#include <iostream>
#include <vector>
#include "../mqcommon/mq_log.hpp"
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_msg.pb.h"

namespace mq
{
    class Router
    {
    public:
        static bool isLegalRoutingKey(const std::string &routing_key)
        {
            // 检查是否合法，查看是否有非法字符就行了。
            for(char ch : routing_key)
            {
                if((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') || 
                    (ch == '_' || ch == '.')
                )
                {
                    continue;
                }
                DLOG("存在非法字符:%s",routing_key.c_str());
                return false;
            }

            return true;
        }
        static bool isLegalBindingKey(const std::string &binding_key)
        {
            // 1.检查是否存在非法字符。
            // 出现则返回。
            for(char ch : binding_key)
            {
                if((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch == '_') || (ch == '.') ||
                    (ch == '*') || (ch == '#')
                )
                {
                    continue;
                }
                DLOG("存在非法字符:%s",binding_key.c_str());
                return false;
            }

            // 2. '*' 和 '#'必须单独在解析的一行中出现。
            // 存在一个'*'或'#'，就不能出现其他字符。
            std::vector<std::string> words;
            Helper::StrHelper::split(binding_key,".",words);
            for(auto& word : words)
            {
                if((word.size() > 1) && 
                    (word.find("*") != std::string::npos ||
                     word.find("#") != std::string::npos)
                )
                {
                    DLOG("存在不合法解析行:%s",word.c_str());
                    return false;
                }
            }
            
            // 3. '*' 和 '#'不能在解析行中连续出现。
            for(int i = 1;i < words.size();++i)
            {
                if(words[i].find("*") != std::string::npos && words[i - 1].find("#") != std::string::npos)
                {
                    DLOG("存在不合法解析行:%s",words[i].c_str());
                    return false;
                }
                else if(words[i].find("#") != std::string::npos && words[i - 1].find("#") != std::string::npos)
                {
                    DLOG("存在不合法解析行:%s",words[i].c_str());
                    return false;
                }
                else if(words[i].find("#") != std::string::npos && words[i - 1].find("*") != std::string::npos)
                {
                    DLOG("存在不合法解析行:%s",words[i].c_str());
                    return false;
                }
            }

            return true;
        }
        static bool route(ExchangeType type, const std::string& binding_key,const std::string& routing_key)
        {
            // DLOG("Router");

            // DLOG("FANOUT?type:%d",type);

            // DLOG("DIRECT?");

            if(type == mq::ExchangeType::FANOUT)
            {
                // DLOG("FANOUT!");

                return true;
            }

            if(type == mq::ExchangeType::DIRECT)
            {
                // DLOG("DIRECT!");

                return (routing_key == binding_key);
            }

            //主题交换：要进行模式匹配    news.#   &   news.music.pop
            //1. 将binding_key与routing_key进行字符串分割，得到各个的单词数组

            std::vector<std::string> b_keys;
            std::vector<std::string> r_keys;

            int n_bkeys = mq::Helper::StrHelper::split(binding_key,".",b_keys);
            int n_rkeys = mq::Helper::StrHelper::split(routing_key,".",r_keys);

            // std::cout << "n_bkeys:" << n_bkeys << std::endl;
            // std::cout << "n_rkeys:" << n_rkeys << std::endl;
            
            //2. 定义标记数组，并初始化[0][0]位置为true，其他位置为false
            std::vector<std::vector<bool>> dp(n_bkeys + 1,std::vector<bool>(n_rkeys + 1,false));
            dp[0][0] = true;

            // '#'代表任意字符，自然都为true。
            //3. 如果binding_key以#起始，则将#对应行的第0列置为1.
            for(int i = 1;i <= b_keys.size();++i)
            {
                if(b_keys[i - 1] == "#")
                {
                    dp[i][0] = true;
                    continue;
                }

                break;
            }

            for(int i = 1;i <= n_bkeys;++i)
            {
                for(int j = 1;j <= n_rkeys;++j)
                {
                    // 一旦匹配就和左上位置一样。
                    if(b_keys[i - 1] == r_keys[j - 1] || b_keys[i - 1] == "*")
                    {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                    else if(b_keys[i - 1] == "#")
                    {
                        //如果当前bkey是个#，则需要从左上，左边，上边继承结果
                        dp[i][j] = dp[i - 1][j - 1] | dp[i - 1][j] | dp[i][j - 1];
                    }
                }
            }

//	    for(auto& str : b_keys)
//            {
//                std::cout << str << std::endl;
//            }
//
//            for(auto& str : r_keys)
//            {
//                std::cout << str << std::endl;
//            }
//
//            for(int i = 0;i <= n_bkeys;++i)
//            {
//                for(int j = 0;j <= n_rkeys;++j)
//                {
//                    std::cout << dp[i][j] << "   ";
//                }
//                std::cout << std::endl;
//            }

            return dp[n_bkeys][n_rkeys];
        }
    private:
        ;
    };
}

#endif
